﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Reflection;
using System.Linq.Expressions;

namespace IntelliLance.Math.Parser
{
    /// <summary>
    /// Represents the base class for all mathematical tokens in a mathematical expression.
    /// </summary>
    [DebuggerDisplay("Token = {TokenCode}, Value = {Value}")]
    public class Token
    {
        /// <summary>
        /// Gets or sets the operator type code for the specified token.
        /// </summary>
        /// <remarks>This property is intended to be used in future releases.</remarks>
        /// <value>The operator type code for the current token.</value>
        public string TokenCode { get; set; }
        /// <summary>
        /// Gets or sets the underlying value of the specified token.
        /// </summary>
        /// <value>The underlying value for the current token.</value>
        public object Value {get;set;}
        /// <summary>
        /// Returns the string representation of the current token.
        /// </summary>
        /// <returns>The string that represents the current token.</returns>
        public override string ToString()
        {
            return string.Format("{0] {1}", this.TokenCode, this.Value);
        }
        /// <summary>
        /// Accepts the underlying visitor.
        /// </summary>
        public virtual void Visit(IVisitor visitor)
        {
            visitor.Accept(this);
        }

    }

    /// <summary>
    /// Represents a right parameters in a mathematical expression.
    /// </summary>
    public class OperatorToken : Token 
    {
        /// <summary>
        /// Gets or sets a Boolean value that determines whether the underlying operator is left associative or not.
        /// </summary>
        /// <value>A Boolean value that specifies if the underlying operator is left associative.</value>
        public bool IsLeftAssociative { get; set; }
        /// <summary>
        /// Gets or sets a Boolean value that determines whether the underlying operator applies to a binary expression or not.
        /// </summary>
        /// <value>A Boolean value that specifies whether the underlying operator is a binary expression operator.</value>
        public bool IsBinary { get; set; }

    }

    /// <summary>
    /// Represents a variable in a mathematical expression.
    /// </summary>
    public class VariableToken : Token
    {
        public Type Type { get; set; }
    }

    /// <summary>
    /// Represents a constant in a mathematical expression.
    /// </summary>
    public class ConstantToken : Token 
    {
        /// <summary>
        /// Gets or sets the value type of constant token.
        /// </summary>
        /// <value>System.Type that represents the underlying constant value.</value>
        public Type Type { get; set; }

    }

    /// <summary>
    /// Represents a function call in a mathematical expression.
    /// </summary>
    public class FunctionToken : Token 
    {
        /// <summary>
        /// Gets or sets a value that represents the function parameters count.
        /// </summary>
        /// <value>An Integer that represents the number of parameters for the underlying method.</value>
        public int ParametersCount { get; set; }
        /// <summary>
        /// Gets or sets a MethodInfo instance that represents that current function token's invocation method.
        /// </summary>
        /// <value>A MethodInfo instance that represents the underlying function.</value>
        public MethodInfo Function { get; set; }

        public Expression Expression { get; set; }

    }

    /// <summary>
    /// Represents the left parenthesis token in a mathematical expression.
    /// </summary>
    public class LeftParenthesisToken : Token
    {
    }

    /// <summary>
    /// Represents the right parenthesis token in a mathematical expression.
    /// </summary>
    public class RightParenthesisToken : Token
    {
    }

    /// <summary>
    /// Represents a parameters separator within a function call in a mathematical expression.
    /// </summary>
    public class FunctionParameterSeparatorToken : Token
    {
    }

}
